#pragma once

#include <memory>
#include <utility>
#include <vector>

#include <jsi/jsi.h>

#include "JsiSkHostObjects.h"

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdocumentation"

#include "JsiSkRuntimeEffect.h"
#include "include/effects/SkRuntimeEffect.h"

#pragma clang diagnostic pop

namespace RNSkia {
namespace jsi = facebook::jsi;

class JsiSkRuntimeShaderBuilder : public JsiSkWrappingSharedPtrHostObject<SkRuntimeShaderBuilder> {
public:
    /* *
     Constructor
     */
    JsiSkRuntimeShaderBuilder(std::shared_ptr<RNSkPlatformContext> context, const SkRuntimeShaderBuilder &rt)
        : JsiSkWrappingSharedPtrHostObject<SkRuntimeShaderBuilder>(std::move(context),
        std::make_shared<SkRuntimeShaderBuilder>(rt))
    {}

    JSI_HOST_FUNCTION(setUniform)
    {
        auto name = arguments[0].asString(runtime).utf8(runtime);
        auto jsiValue = arguments[1].asObject(runtime).asArray(runtime);
        auto size = jsiValue.size(runtime);
        std::vector<SkScalar> value;
        value.reserve(size);
        for (int i = 0; i < size; i++) {
            auto e = jsiValue.getValueAtIndex(runtime, i).asNumber();
            value.push_back(e);
        }
        getObject()->uniform(name.c_str()).set(value.data(), static_cast<int>(size));
        return jsi::Value::undefined();
    }

    JSI_EXPORT_FUNCTIONS(JSI_EXPORT_FUNC(JsiSkRuntimeShaderBuilder, setUniform),
        JSI_EXPORT_FUNC(JsiSkRuntimeShaderBuilder, dispose))

    /* *
      Returns the jsi object from a host object of this type
     */
    static jsi::Value toValue(jsi::Runtime &runtime, std::shared_ptr<RNSkPlatformContext> context,
        const SkRuntimeShaderBuilder &rt)
    {
        return jsi::Object::createFromHostObject(runtime,
            std::make_shared<JsiSkRuntimeShaderBuilder>(std::move(context), rt));
    }

    /* *
     * Creates the function for construction a new instance of the SkRect
     * wrapper
     * @param context platform context
     * @return A function for creating a new host object wrapper for the SkRect
     * class
     */
    static const jsi::HostFunctionType createCtor(std::shared_ptr<RNSkPlatformContext> context)
    {
        return JSI_HOST_FUNCTION_LAMBDA
        {
            auto rt = JsiSkRuntimeEffect::fromValue(runtime, arguments[0]);
            auto rtb = SkRuntimeShaderBuilder(rt);
            // Return the newly constructed object
            return jsi::Object::createFromHostObject(runtime,
                std::make_shared<JsiSkRuntimeShaderBuilder>(std::move(context), std::move(rtb)));
        };
    }
};
} // namespace RNSkia
